﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Globalization;
using System.Linq;
using System.Linq.Expressions;
using System.Web.Security;
using anrControls;
using Argotic.Extensions.Core;
using Argotic.Syndication;
using Castle.MonoRail.Framework;
using Castle.MonoRail.Framework.Filters;
using StateTheater.Models;
using StateTheaterDataModel;


namespace StateTheater.Controllers
{
	[Layout("default"), Rescue("generalerror")]
	[Filter(ExecuteWhen.BeforeAction, typeof(MobileFilter))]
	public class AuditionController : SmartDispatcherController
	{
		StateTheaterDataContext db;
		public AuditionController(StateTheaterDataContext db)
		{
			this.db = db;
		}

		static private int MemberId
		{
			get
			{
				return (int)Membership.GetUser().ProviderUserKey;
			}
		}

		private List<AuditionDetails> GetDetails()
		{
			var auditions = (from a in db.Auditions
							 where a.LastDate > DateTime.Now.AddDays(-1)
							 && a.FirstDate < DateTime.Now.AddDays(60)
							 orderby a.FirstDate
							 select new // AuditionDetails
										{
											FirstDate = a.FirstDate,
											LastDate = a.LastDate,
											Notes = a.Notes,
											ProductionID = a.ProductionID,
											Production = a.Production,
											ID = a.EventID,
											Member_ID = a.Member_ID
										});

			List<AuditionDetails> details = new List<AuditionDetails>();
			foreach (var aud in auditions)
			{
				if (aud.Production != null)
				{
					AuditionDetails audition = new AuditionDetails()
					{
						FirstDate = aud.FirstDate,
						ID = aud.ID,
						LastDate = aud.LastDate,
						Title = Util.AdjTitle(aud.Production.Play.Title),
						Troupe = Util.AdjTitle(aud.Production.Troupe.Name),
						ShortName = aud.Production.Troupe.shortname,
						TroupeID = aud.Production.TroupeID,
						MemberID = aud.Member_ID,
						Notes = aud.Notes,
						NotesLen = aud.Notes == null ? 0 : aud.Notes.Length,
						ProductionID = aud.ProductionID,
						Venue = aud.Production.Venue.Name,
						City = aud.Production.Venue.City
					};
					details.Add(audition);
				}
				else
				{
					AuditionDetails audition = new AuditionDetails()
					{
						FirstDate = aud.FirstDate,
						ID = aud.ID,
						LastDate = aud.LastDate,
						Title = "",
						Troupe = "",
						TroupeID = 0,
						MemberID = aud.Member_ID,
						Notes = aud.Notes,
						NotesLen = aud.Notes == null ? 0 : aud.Notes.Length,
						ProductionID = 0
					};
					details.Add(audition);
				}
			}
			return details;
		}
		public void display()
		{
			List<AuditionDetails> details = GetDetails();

			PropertyBag["Auditions"] = details;
		   
					  /*
			SELECT     ProductionID, FirstDate, LastDate, Notes, ForumCode
FROM         [NewNJT_Admin  ].Auditions
WHERE     (LastDate > GETDATE() - 1) AND (FirstDate < GETDATE() + 60)
					  */

		}

		public void Rss()
		{
			CancelView();
			Response.ContentType = "application/rss+xml";
			var when = DateTime.Now;
			var md = new Markdown();

			List<AuditionDetails> details = GetDetails();
			Uri uri = Request.Uri;
			RssFeed feed = new RssFeed(uri, "NJTheater.com -  - Auditions Channel");
			feed.Channel.Description = "List of auditions for theatrical productions on all levels in New Jersey for two months starting {0:M/d/yyyy}".With(when);
			feed.Channel.ManagingEditor = ConfigurationManager.AppSettings["SysadminEmail"];
			feed.Channel.Webmaster = ConfigurationManager.AppSettings["SysadminEmail"];
			feed.Channel.Language = CultureInfo.CurrentCulture;

			feed.Channel.Image = new RssImage();
			feed.Channel.Image.Title = "NJTheater.com";
			var photo = new UriBuilder(uri);
			photo.Path = this.Context.ApplicationPath + "/content/images/NJTheaterMask.gif";
			feed.Channel.Image.Url = photo.Uri;
			feed.Channel.Image.Link = uri;
			feed.Channel.Image.Width = 141;
			feed.Channel.Image.Height = 145;

			foreach (var aud in details)
			{
				RssItem item = new RssItem();
				var ev = new EventSyndicationExtension();
				if (aud.ProductionID == 0)
					item.Title = "Production";
				else
				{
										
					item.Title = HttpContext.Server.HtmlDecode("{0} ({1})".With(aud.Title, aud.Troupe));
					var link = new UriBuilder(uri);
					link.Path = this.Context.ApplicationPath + "/Show/{0}/Display.rails".With(aud.ProductionID);
					item.Link = link.Uri;
					ev.Context.Location = "{0}, {1}".With(aud.Venue, aud.City);
				}

				if (aud.NotesLen > 0)
					item.Description = @"({0:d}-{1:d}) {2}".With(aud.FirstDate, aud.LastDate, md.Transform(aud.Notes));
				else
					item.Description = @"({0:d}-{1:d})".With(aud.FirstDate, aud.LastDate);

				if (aud.TroupeID != 0)
				{
					ev.Context.Organizer = aud.Troupe;
				}
				ev.Context.Type = "audition";
				ev.Context.StartDate = aud.FirstDate;
				ev.Context.EndDate = aud.LastDate;
				item.AddExtension(ev);

				item.PublicationDate = DateTime.Today;
				feed.Channel.AddItem(item);
			}

			feed.Save(Response.OutputStream);
		}

		private List<AuditionDetails> GetAuditionForCurrentUser()
		{
			return GetAuditionForUser(MemberId);
		}

		private List<AuditionDetails> GetAuditionForUser(int memberId)
		{
			var basic = (from a in db.Auditions
						 //                         join p in db.Productions on a.ProductionID equals p.ProductionID
						 //                        join pl in db.Plays on p.PlayID equals pl.PlayID			 // joins implied below.
						 where a.ProductionID != 0					// Not actually necessary (forced by joins below) but helpful for clarity
						 select new AuditionDetails
						 {
							 ID = a.EventID,
							 Title = a.Production.Play.Title,
							 FirstDate = a.FirstDate,
							 LastDate = a.LastDate,
							 NotesLen = (a.Notes == null) ? 0 : a.Notes.Length,
							 ProductionID = a.ProductionID,
							 MemberID = a.Member_ID,
							 TroupeID = a.Production.TroupeID,
							 Troupe = a.Production.Troupe.Name,
							 VeryOld = (DateTime.Now - a.LastDate).Days > 30
						 }).Union(from a in db.Auditions
								  where a.ProductionID == null || a.ProductionID == 0
								  select new AuditionDetails
								  {
									  ID = a.EventID,
									  Title = "Audition",
									  FirstDate = a.FirstDate,
									  LastDate = a.LastDate,
									  NotesLen = (a.Notes == null) ? 0 : a.Notes.Length,
									  ProductionID = a.ProductionID,
									  MemberID = a.Member_ID,
									  TroupeID = 0,
									  Troupe = "",
									  VeryOld = (DateTime.Now - a.LastDate).Days > 30
								  });

			if (!(Roles.IsUserInRole("Admin") || Roles.IsUserInRole("Super")))
			{
				// If this member is allowed to edit auditions for this troupe
				var troupes = (from tp in db.TroupePermissions
							   where tp.MEMBER_ID == memberId
							   select tp.Troupeid);

				// or if this user entered it originally.
				basic = (basic.Where(a => troupes.Contains(a.TroupeID) || a.MemberID == memberId));
			}

			return basic.OrderBy(a => a.LastDate).ToList();

		}

		public void Select()
		{
			PropertyBag["auditions"] = GetAuditionForCurrentUser();
		}



		public void Delete(int id)
		{
			DeleteDirect(id);
			RenderView("select");
			Select();
		}

		[return:JSONReturnBinder]
		[Rescue(typeof(JsonRescueController))]
		public Status DeleteDirect(int id)
		{
			Audition aud = db.Auditions.SingleOrDefault(a => a.EventID == id);
			db.Auditions.DeleteOnSubmit(aud);
			db.SubmitChanges();
			return Status.OK;
		}

		public void New()
		{
			Edit(new AuditionDetails());
		}

		public  void Edit(int id)
		{
			AuditionDetails aud = GetAuditionByID(db, id);
			Edit(aud);
		}

		public void EditProd(int id)
		{
			var aud = GetAuditionByProduction(db, id);
			if (aud == null)
			{
//				this.RenderView("Select");
//				Select();
				aud = new AuditionDetails();
				aud.ProductionID = id;
			}
//			else
			{
				RenderView("Edit");
				Edit(aud);
			}
		}

		public void Edit([DataBind("audition")] AuditionDetails audition)
		{
			var prod = (from p in db.Productions
						where p.FirstPerformance > DateTime.Now
						orderby p.Play.Title
						select new
						{
							ProductionID = p.ProductionID,
							Title = p.Play.Title,
							Venue = p.Venue.Name,
							Year = p.FirstPerformance.Year
						});

//			db.Log = new Castle.MonoRail.Framework.Internal.ProperyBagTextWriter("log", PropertyBag);

			var listProd = prod.ToList();
			PropertyBag["productions"] = listProd;
			audition.MemberID = MemberId;
			PropertyBag["audition"] = audition;
			PropertyBag["Ajax"] = Helpers["Ajax"];
			PropertyBag["AjaxHelper"] = Helpers["Ajax"];
			RenderView("edit");
		}

		public void Save([DataBind("audition")] AuditionDetails audition)
		{
			Audition rec;
			if (audition.ID == 0)
			{
				rec = new Audition();
				db.Auditions.InsertOnSubmit(rec);
				PropertyBag["state"] = "Added";
			}
			else
			{
				rec = (from a in db.Auditions
					   where a.EventID == audition.ID
					   select a).FirstOrDefault();
				PropertyBag["state"] = "Updated";
			}

			rec.Member_ID = audition.MemberID;
			rec.FirstDate = audition.FirstDate;
			rec.LastDate = audition.LastDate;
			rec.Notes = audition.Notes;
			rec.ProductionID = audition.ProductionID == 0 ? null : audition.ProductionID;
			db.SubmitChanges();

			PropertyBag["audition"] = audition; ;
			AdminController.RecordUserAction(db, this, "audition", audition.ID, this.PropertyBag);
			RenderView("select");
			Select();
		}

		public static AuditionDetails GetAuditionByID(StateTheaterDataContext db, int auditionid)
		{
			return GetAuditionBy(db, a=>(a.EventID == auditionid));
		}
		public static AuditionDetails GetAuditionByProduction(StateTheaterDataContext db, int prodid)
		{
			return GetAuditionBy(db, a => a.ProductionID == prodid);
		}

		private static AuditionDetails GetAuditionBy(StateTheaterDataContext db, Expression<Func<Audition, bool>> whereClause)
		{
			AuditionDetails aud = db.Auditions
				.Where(whereClause)
				.Select(a => new AuditionDetails()
				{
					FirstDate = a.FirstDate,
					ID = a.EventID,
					LastDate = a.LastDate,
					MemberID = a.Member_ID,
					Notes = a.Notes,
					NotesLen = String.IsNullOrEmpty(a.Notes) ? 0 : a.Notes.Length,
					ProductionID = a.ProductionID,
				}
				).FirstOrDefault();

			return aud;
		}
	}
}
